﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using System.Net;
using System.Web;
using System.Xml.Serialization;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

public class ClosureCompiler : Task
{
    [Required]
    public ITaskItem[] SourceFiles { get; set; }

    [Required]
    public String SourceExtensionPattern { get; set; }

    [Required]
    public String TargetExtension { get; set; }

    private String _CompilationLevel = "WHITESPACE_ONLY";
    public String CompilationLevel
    {
        get { return _CompilationLevel; }
        set { _CompilationLevel = value; }
    }

    private String _ApiUrl = "http://closure-compiler.appspot.com/compile";
    public String ApiUrl
    {
        get { return _ApiUrl; }
        set { _ApiUrl = value; }
    }

    public override bool Execute()
    {
        Log.LogMessage(MessageImportance.High, String.Concat("Source Files Count: ", SourceFiles.Count()), null);
        foreach (var t in SourceFiles)
        {
            try
            {
                Log.LogMessage(MessageImportance.High, String.Concat("Compiling File: ", t.ItemSpec), null);

                var source = File.ReadAllText(t.ItemSpec);
                var compiledSource = CompileFile(source);
                var newFileName = Regex.Replace(t.ItemSpec, SourceExtensionPattern, TargetExtension);

                File.WriteAllText(newFileName, compiledSource.SelectSingleNode("//compiledCode").InnerText);
                Log.LogMessage(MessageImportance.High, String.Concat("File Compiled As: ", newFileName), null);
            }
            catch (Exception ex)
            {
                Log.LogMessage(MessageImportance.High, String.Concat("Compilation Failed: ", t.ItemSpec, ", Reason: ", ex.Message), null);
            }
        }

        return true;
    }

    private XmlDocument CompileFile(String source)
    {

        var postData = new Dictionary<String, String>();
        postData.Add("js_code", source);
        postData.Add("compilation_level", CompilationLevel);
        postData.Add("output_format", "xml");
        postData.Add("output_info", "compiled_code");

        var sb = new StringBuilder();
        foreach (var e in postData)
        {
            if (sb.Length > 0)
            {
                sb.Append("&");
            }

            sb.Append(e.Key);
            sb.Append("=");
            sb.Append(e.Value);
        }
        
        var data = Encoding.UTF8.GetBytes(sb.ToString());
        var request = (HttpWebRequest)WebRequest.Create(ApiUrl);
        request.ContentLength = data.Length;
        request.ContentType = "application/x-www-form-urlencoded";
        request.Method = "POST";

        var requestStream = request.GetRequestStream();
        requestStream.Write(data, 0, data.Length);

        var response = (HttpWebResponse)request.GetResponse();
        var dataStream = response.GetResponseStream();

        var reader = XmlReader.Create(dataStream);
        var xml = new XmlDocument();
        xml.Load(reader);

        requestStream.Close();
        reader.Close();
        dataStream.Close();
        response.Close();

        return xml;
    }
}
